﻿using System;
using System.Collections.Generic;
using System.Linq;

using NHibernate.Criterion;

using Inovout.Runtime;
using Inovout.Services;

using Inovout.Cloud.DataStore.Models;
using Inovout.Cloud.DataStore.Utility;


namespace Inovout.Cloud.DataStore.Services
{
    public class TableService : RepositoryService<Table>, ITableService
    {
        private IDatabaseService databaseService = null;
        private MongoDbClient _mongoDbClient;
        protected MongoDbClient MongoDbClient
        {
            get
            {
                if (_mongoDbClient == null)
                {
                    _mongoDbClient = new MongoDbClient(ComponentRegistry.Resolve<IApplication>().Settings["MongoDbConnectionString"].ToString());
                }

                return _mongoDbClient;
            }
        }

        public TableService(IDatabaseService databaseService)
        {
            this.databaseService = databaseService;
        }

        /// <summary>
        /// 创建表
        /// </summary>
        /// <param name="table">表的基本信息</param>
        /// <returns>表信息</returns>
        public Table CreateTable(Table table)
        {
            if (table == null || table.Database == null || String.IsNullOrEmpty(table.Name))
            {
                return null;
            }

            Table tb = FindByName(table.Database, table.Name);
            if (tb != null)
            {
                return tb;
            }

            Database database = this.databaseService.CreateDatabase(table.Database);

            //todo:如果不成功，在MongoDbClient内抛异常。
            bool isSuccess = MongoDbClient.CreateTable(table.Database.Name, table.Name);

            if (isSuccess)
            {
                //创建表
                base.Create(table);

                Table newTable = FindByName(database, table.Name);

                //创建表的属性
                if (table.Properties != null && table.Properties.Count > 0)
                {
                    List<Models.Property> properties = new List<Models.Property>();

                    foreach (Models.Property property in table.Properties)
                    {
                        property.Table = newTable;
                        properties.Add(property);
                    }

                    IPropertyService propertyService = ComponentRegistry.Resolve<IPropertyService>();
                    propertyService.CreateProperties(properties);
                }

                return newTable;
            }

            return null;
        }

        /// <summary>
        /// 删除表
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="tableName">表名</param>
        /// <returns>是否操作成功</returns>
        public bool DropTable(Database database, string tableName)
        {
            if (database == null || String.IsNullOrEmpty(tableName))
            {
                return false;
            }

            Table table = FindByName(database, tableName);
            if (table == null)
            {
                return true;
            }

            table.Database.Tables.Remove(table);
            table.Database = null;
            base.Delete((object)table.Id);

            bool isSuccess = this.MongoDbClient.DropTable(database.Name, tableName);

            return isSuccess;
        }

        /// <summary>
        /// 取得某个数据库下的某个表
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="tableName">表名</param>
        /// <returns>表</returns>
        public Table FindByName(Database database, string tableName)
        {
            if (database == null || String.IsNullOrEmpty(tableName))
            {
                return null;
            }

            return base.Repository.Find(Restrictions.Eq("Database.Id", database.Id),
                                            Restrictions.Eq("Name", tableName).IgnoreCase());
        }

        /// <summary>
        /// 取得某个数据库下的所有表信息
        /// </summary>
        /// <param name="database">数据库</param>
        /// <returns>所有表信息</returns>
        public IEnumerable<Table> GetAllTables(Database database)
        {
            return base.Repository.FindAll(Restrictions.Eq("Database.Id", database.Id));
        }

        /// <summary>
        /// 判断表是否存在
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="tableName">表名</param>
        /// <returns>表是否存在</returns>
        public bool TableExists(Database database, string tableName)
        {
            Table table = FindByName(database, tableName);
            if (table == null)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 给表重命名
        /// </summary>
        /// <param name="database">数据库</param>
        /// <param name="oldTableName">表的原始名称</param>
        /// <param name="newTableName">表的新名称</param>
        /// <returns>是否操作成功</returns>
        public bool ReNameTable(Database database, string oldTableName, string newTableName)
        {
            if (database == null || String.IsNullOrEmpty(oldTableName) || String.IsNullOrEmpty(newTableName))
            {
                return false;
            }

            Table table = FindByName(database, oldTableName);
            if (table == null)
            {
                return false;
            }

            bool isSuccess = MongoDbClient.RenameTable(database.Name, oldTableName, newTableName);

            if (isSuccess)
            {
                table.Name = newTableName.Trim();
                base.Update(table);
            }

            return isSuccess;
        }

        /// <summary>
        /// 删除数据库的所有表
        /// </summary>
        /// <param name="database"></param>
        public void DropAllTables(Database database)
        {
            IEnumerable<Table> allTables = GetAllTables(database);

            if (allTables == null || allTables.Count() == 0)
            {
                return;
            }

            foreach (Table table in allTables)
            {
                table.Database.Tables.Remove(table);
                table.Database = null;
                base.Delete((object)table.Id);
                this.MongoDbClient.DropTable(database.Name, table.Name);
            }
        }
    }
}
